package com.ksd.pug.service.article;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ksd.orm.pug.mapper.ArticleCommentMapper;
import com.ksd.pug.commons.threadlocal.UserThrealLocal;
import com.ksd.pug.commons.utils.fn.asserts.Vsserts;
import com.ksd.pug.pojo.ArticleComment;
import com.ksd.pug.pojo.SysLoginUser;
import com.ksd.pug.utils.redis.PugRedisOperator;
import com.ksd.pug.vo.comment.ArticleCommentPageVo;
import com.ksd.pug.vo.comment.ArticleCommentVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 飞哥
 * @Title: 学相伴出品
 * @Description: 飞哥B站地址：https://space.bilibili.com/490711252
 * 记得关注和三连哦！
 * @Description: 我们有一个学习网站：https://www.kuangstudy.com
 * @date 2022/3/19$ 16:58$
 */
@Service
@Slf4j
public class ArticleCommentServiceImpl extends ServiceImpl<ArticleCommentMapper, ArticleComment> implements IArticleCommentService {


    @Autowired
    private PugRedisOperator redisOperator;

    /**
     * 查询所有文章评论
     * @param articleCommentPageVo
     * @return
     */
    @Override
    public Page<ArticleComment> loadArticleComment(ArticleCommentPageVo articleCommentPageVo) {
        //1: 查询第一级的评论
        Page<ArticleComment> articleCommentPage = loadCommentChildren(articleCommentPageVo.getArticleId(),
                articleCommentPageVo.getParentId(), articleCommentPageVo.getPageNo(), articleCommentPageVo.getPageSize());
        //2：处理子集的评论
        List<ArticleComment> articleCommentBoList = articleCommentPage.getRecords();
        //3: 如果你没有查询到评论数据
        if (Vsserts.isNotEmptyCollection(articleCommentBoList)) {
            // 用户点赞的评论查询出来
            SysLoginUser user = UserThrealLocal.get();
            log.info("======================当前用户是{}",user);
            articleCommentBoList = articleCommentBoList.stream().peek(hc -> {
                //1:  把每一评论的对应子评论查询处理。这里有问题为啥是分页对象呢.方便子集进行分页处理
                Page<ArticleComment> pageChildrenBo = loadCommentChildren(articleCommentPageVo.getArticleId(),
                        hc.getId(), 1, 3);
                hc.setPageChildrens(pageChildrenBo);
                //查询子集数量
                LambdaQueryWrapper<ArticleComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(ArticleComment::getArticleId, articleCommentPageVo.getArticleId());
                lambdaQueryWrapper.eq(ArticleComment::getParentId, hc.getId());
                Long count = this.count(lambdaQueryWrapper);
                hc.setChildrenNums(count);
                // 2: 把redis中每个点赞的赞数返回
                String countStr = redisOperator.getHashValue("redis:user:comment:like",hc.getId()+"");
                if(Vsserts.isNotEmpty(countStr)) {
                    hc.setZannum(Integer.valueOf(countStr));
                }else{
                    hc.setZannum(0);
                }

                // 3: 获取某个用户是否点击某个评论的赞
                if(Vsserts.isNotNull(user)){
                    log.info("当前点赞用户是{}",user);
                    String hget = redisOperator.hget("redis:comment:like:user", user.getId() + ":" + hc.getId());
                    if (Vsserts.isNotEmpty(hget)) {
                        hc.setIszan(1);
                    } else {
                        hc.setIszan(0);
                    }
                }
                else{
                    hc.setIszan(0);
                }

            }).collect(Collectors.toList());
            // 把处理好的结果返回到数据中
            articleCommentPage.setRecords(articleCommentBoList);
        }
        // 4:返回
        return articleCommentPage;
    }

    /**
     * 查询文章子评论分页
     *
     * @param articleId
     * @param parentId
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public Page<ArticleComment> loadCommentChildren(Long articleId, Long parentId, Integer pageNo, Integer pageSize) {
        Page<ArticleComment> page = new Page<>(pageNo, pageSize);
        //2:设置条件
        LambdaQueryWrapper<ArticleComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ArticleComment::getArticleId, articleId);
        lambdaQueryWrapper.eq(ArticleComment::getParentId, parentId);
        //3:设置排序
        lambdaQueryWrapper.orderByDesc(ArticleComment::getCreateTime);
        // 3: 查询返回
        return this.page(page, lambdaQueryWrapper);
    }


    /**
     * 保存文章评论
     * @param articleCommentVo
     * @return
     */
    @Override
    public ArticleComment saveArticleComment(ArticleCommentVo articleCommentVo) {
        // 或者用户的信息
        SysLoginUser user = UserThrealLocal.get();
        // 1: 把用户填写的信息针对某个文章评论的信息进行填写pojo
        ArticleComment articleComment = new ArticleComment();
        // 用户前台输入的信息
        articleComment.setArticleId(articleCommentVo.getArticleId());
        articleComment.setContent(articleCommentVo.getContent());
        articleComment.setParentId(articleCommentVo.getParentId());

        if (articleCommentVo.getParentId() != null && articleCommentVo.getParentId().equals(0L)) {
            // 用户信息的获取
            articleComment.setUserid(user.getId());
            articleComment.setUsernickname(user.getNickname());
            articleComment.setUseravatar(user.getAvatar());
            // 保存用户评论到评论表中
            boolean b = this.saveOrUpdate(articleComment);
            // 用redis来记录评论总数 -- 有坑
            // 1: redis集群 ---
            // 2: 本地缓存
            // 3: rabbitmq
            redisOperator.increment("article:comment:count:"+articleComment.getArticleId(),1L);
            return articleComment;
        } else {
            // 这个这是去补齐数据，如果不做的也可以
            ArticleComment parentArticleComment = this.getById(articleComment.getParentId());
            if (Vsserts.isNotNull(parentArticleComment)) {
                articleComment.setUserid(parentArticleComment.getUserid());
                articleComment.setUsernickname(parentArticleComment.getUsernickname());
                articleComment.setUseravatar(parentArticleComment.getUseravatar());
            }
            // 用户信息的获取
            articleComment.setReplyUserid(user.getId());
            articleComment.setReplyUsernickname(user.getNickname());
            articleComment.setReplyUseravatar(user.getAvatar());
            // 保存用户评论到评论表中
            boolean b = this.saveOrUpdate(articleComment);
            // 用redis来记录评论总数 -- 有坑
            // 1: redis集群 ---
            // 2: 本地缓存
            // 3: rabbitmq
            redisOperator.increment("article:comment:count:"+articleComment.getArticleId(),1L);
            return articleComment;
        }
    }

    /**
     * 保存文章评论
     * @param commentId 评论的主健
     * @param userId 用户ID 考虑到一个安全性的问题
     * @return
     */
    @Override
    public boolean delArticleComment(Long articleId, Long commentId, Long userId) {
        LambdaQueryWrapper<ArticleComment> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ArticleComment::getUserid, userId);
        lambdaQueryWrapper.eq(ArticleComment::getId, commentId);
        boolean remove = this.remove(lambdaQueryWrapper);
        redisOperator.decrement("article:comment:count:"+articleId,1L);
        return remove;
    }

    /**
     * 评论赞+1
     * @param commentId
     * @return
     */
    @Override
    @Transactional
    public int updateCommentPlusZannum(@Param("commentId")Long commentId){
        SysLoginUser user = UserThrealLocal.get();
        //1: 评论表zannum + 1
        redisOperator.incrementHash("redis:user:comment:like",commentId+"",1L);
        redisOperator.setHashValue("redis:comment:like:user", user.getId() + ":" + commentId, "1");
        return 1;
    }

    /**
     * 评论赞 - 1
     * @param commentId
     * @return
     */
    @Override
    @Transactional
    public int updateCommentMiusZannum(@Param("commentId")Long commentId){
        SysLoginUser user = UserThrealLocal.get();
        //1: 评论表zannum + 1
        redisOperator.decrementHash("redis:user:comment:like",commentId+"",1L);
        redisOperator.hdel("redis:comment:like:user", user.getId() + ":" + commentId);
        return 1;
    }



}
